﻿//----------------------------------------------------------------
// Desc: 
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2009-10-15
//
// Update Date :            
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


//----------------------------------------------------------------
// 多行编辑逻辑
//----------------------------------------------------------------
class FUI_RichEdit;
class FAPI FU_RE_RICH : public FU_EDIT_DATA
{
    FUI_DECLARE_CLASS(FU_RE_RICH);

public:
    class RICH_LINE : public FU_EDIT_DATA
    {
        FUI_DECLARE_CLASS(RICH_LINE)

    public:
        BYTE cursor;            // 有没有光标
        size_t head_idx;        // 我在字符表中的索引
        size_t offset_h;        // 相对于0的高度偏移
        FU_RE_RICH* edr;

        RICH_LINE(FU_RE_RICH* p, size_t idx, size_t oh);
        virtual~RICH_LINE(){ Clear(); }
        virtual void GetChar(FUI_INIT* uit, const WCHAR* ch, size_t& w, size_t& h){ return edr->GetChar(uit, ch, w, h); }
        virtual FU_EDIT_CHAR* AllocChar(){ return edr->AllocChar(); }
        virtual void FreeChar(FU_EDIT_CHAR* p){ edr->FreeChar(p); }
        virtual size_t MinHeight(){ return (size_t)edr->MinHeight(); }
    };
    typedef FUI_Vector< RICH_LINE* > FV_UI_PRICH_LINE;

public:
    FUI_RichEdit* pRich;
    FV_UI_PEDIT_CHAR unusedChar;
    FV_UI_PRICH_LINE unusedLine;
    FV_UI_PRICH_LINE vLines;

    FU_RE_RICH();
    virtual~FU_RE_RICH();
    virtual void ClearLines();
    virtual void GetChar(FUI_INIT* uit, const WCHAR* ch, size_t& w, size_t& h);
    virtual size_t MinHeight();
    virtual void RefHeight();
    virtual void Clear();
    virtual FU_EDIT_CHAR* AllocChar();
    virtual void FreeChar(FU_EDIT_CHAR* p){ unusedChar.push_back(p); }
    virtual RICH_LINE* AllocLine(size_t idx, size_t oh);
    virtual void FreeLine(RICH_LINE* p){ unusedLine.push_back(p); }
    virtual bool Set(size_t p, bool shift);
    virtual RICH_LINE* CurLine(size_t* idx = 0);
    virtual void Move(EF_CURSOR_MOVE dir, FU_EDIT_CURSOR& ec);
    // 屏蔽横向取索引功能
    virtual size_t CursorIndex(funit cx, size_t force_w){ return 0; }
    virtual size_t OffsetH();
    // 找到偏移坐标对应的文字索引和行索引
    // .cx,cy 是相对于控件工作区的编移
    virtual bool CursorIndexXY(funit cx, funit cy, size_t& x_idx, size_t& l_idx);
    virtual void UpdateLines();
    virtual void RenderBlock(FUI_INIT* uit, fuRect& rc, DWORD color);
    virtual void RenderText(FUI_INIT* uit, fuRect& rc, DWORD fnt_id, fuFontGroup* fg, BYTE efc, FUI_StringW& password, bool ray, DWORD ray_color);
    virtual void GetRect(fuRect& rc);
    virtual void UpdateCtrl();
};


//----------------------------------------------------------------
//
//----------------------------------------------------------------
class FAPI FUI_RichEdit : public FUI_Object
{
    FUI_DECLARE_CLASS(FUI_RichEdit)

public:
    FUI_RichEdit(EF_UI_WIDGET_TYPE t = eUWT_RichEdit);
    virtual~FUI_RichEdit();
    virtual void Render(EF_UI_RENDER_LAYER layer);
    virtual void UpdateRect();
    virtual bool IsChild(FUI_Object* pChild);
    virtual bool HasClip(){ return !richDT->vLines.empty(); }
    virtual bool CanGetFocus() { return FUI_Object::CanGetFocus() && !IsReadOnly(); }
    virtual const WCHAR* GetText(){ return richDT->szText.c_str(); }
    virtual const WCHAR* GetSelectText(){ return richDT->szSelect.c_str(); }
    virtual void SetWidth(funit w);
    virtual void SetHeight(funit h);
    virtual void SetText(const WCHAR* text);
    virtual void SetText(const ACHAR* text);
    virtual bool OnChar(unsigned int nChar);
    virtual bool OnKeyDown(unsigned int nChar);
    virtual bool OnMouseMove(funit nX, funit nY);
    virtual bool OnMouseWheel(bool bUp, funit nX, funit nY);
    virtual bool OnLButtonDown(funit nX, funit nY);
    virtual bool OnLButtonUp(funit nX, funit nY);
    virtual bool OnLButtonDBClick(funit nX, funit nY);
    virtual void OnFrameHide(bool visable);

    // 清空
    virtual void Clear(){ richDT->Clear(); }
    // 复制
    virtual bool Copy();
    // 剪切
    virtual bool Cut();
    // 粘贴
    virtual bool Paste();
    // 全选
    virtual void SelectAll();
    // 创建和消毁编辑逻辑
    virtual void _CreateDestoryEdit(bool create);

    // 设置状态
    FINLINE void SetReadOnly(bool b){ pRichData->SetReadOnly(b); }
    FINLINE bool IsReadOnly(){ return pRichData->IsReadOnly(); }
    FINLINE void SetMaxLength(WORD n){ pRichData->nMaxLength; }
    FINLINE WORD GetMaxLength(){ return pRichData->nMaxLength; }
    FINLINE size_t GetOffsetH(){ return (size_t)uScrollBar.GetValue(); }
    // 获取部分控件数据
    FINLINE FUI_ScrollBar& GetScroll(){ return uScrollBar; }

protected:
    virtual void InitUIData(FUI_Object* father, fuWidgetBase* pData, FUI_Layout* layout);
    virtual void Update();

protected:
    fuWidgetRichEdit* pRichData; // 控件数据地址
    FUI_ScrollBar uScrollBar; // 滚动条
    bool bLButtonDown;      // 鼠标是否按下
    DWORD dwRayStart;       // 闪烁的开始时间
    NCHAR szAppendChar[3];  // 等待加入串的字符 szAppendChar[2]永远保持为0
    FU_RE_RICH* richDT;     // 多编辑器
};


FINLINE void FU_RE_RICH::GetChar(FUI_INIT* uit, const WCHAR* ch, size_t& w, size_t& h)
{
    uit->query_fnt(uit, pRich->GetFontIndex(), ch, false, 0, w, h);
}
FINLINE size_t FU_RE_RICH::MinHeight()
{
    return (size_t)pRich->GetCharHeight();
}
FINLINE size_t FU_RE_RICH::OffsetH()
{
    return pRich->GetOffsetH();
}
FINLINE void FU_RE_RICH::GetRect(fuRect& rc)
{
    pRich->GetWorkRect(&rc);
}
FINLINE void FU_RE_RICH::UpdateCtrl()
{
    pRich->NeedUpdateRect();
}